package cl.zeke.cursos.jsf2spring3jpa2.dao;

import cl.zeke.cursos.jsf2spring3jpa2.negocio.entities.Perfil;
import cl.zeke.cursos.jsf2spring3jpa2.negocio.entities.Usuario;
import java.util.Date;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.hibernate.Criteria;
import org.hibernate.FetchMode;
import org.hibernate.Session;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.sql.JoinType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Repository;

@Repository
public class UsuarioDao {
    
    private static Logger log = LoggerFactory.getLogger(UsuarioDao.class);

    @PersistenceContext
    private EntityManager em;
    
    public List<Usuario> traerTodos() {
        return em.createNamedQuery("Usuario.traerTodos", Usuario.class)
                .getResultList();
    }
    
    public Usuario traerPorRut(Integer rut) {
        List<Usuario> lista = em.createNamedQuery("Usuario.traerPorRut")
                .setParameter("rut", rut)
                .getResultList();
        if(lista.isEmpty()) {
            return null;
        }
        return lista.get(0);
    }

    public List<Usuario> buscar(String nombres, String apellidos, Integer rut, Perfil perfil, String email, Date fechaNacimientoInferior, Date fechaNacimientoSuperior, Boolean habilitado, int inicio, int fin) {
        Criteria criteria = criteriaFiltroUsuarios(nombres, apellidos, rut, perfil, email, fechaNacimientoInferior, fechaNacimientoSuperior, habilitado);
        return criteria
                .setFirstResult(inicio)
                .setMaxResults(fin)
                .list();
    }

    public int buscarRowCount(String nombres, String apellidos, Integer rut, Perfil perfil, String email, Date fechaNacimientoInferior, Date fechaNacimientoSuperior, Boolean habilitado) {
        Criteria criteria = criteriaFiltroUsuarios(nombres, apellidos, rut, perfil, email, fechaNacimientoInferior, fechaNacimientoSuperior, habilitado);
        return ((Number)criteria.setProjection(Projections.rowCount()).uniqueResult()).intValue();
    }
    
    public Usuario traerPorEmail(String email) {
        List<Usuario> list=  em.createNamedQuery("Usuario.traerPorEmail")
                .setParameter("email", email)
                .getResultList();
        if(list.isEmpty()) {
            return null;
        }
        return list.get(0);
    }
    
    
    //PRIVADOS
    
    private Criteria criteriaFiltroUsuarios(
            String nombres, 
            String apellidos, 
            Integer rut, 
            Perfil perfil, 
            String email, 
            Date fechaNacimientoInferior, 
            Date fechaNacimientoSuperior,
            Boolean habilitado) 
    {
        Session hibernateSession = (Session) em.getDelegate();
        Criteria criteria = hibernateSession.createCriteria(Usuario.class, "usuario");
        
         //select distinct
        criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); 
        
        //join fetchs
        criteria.createAlias("usuario.perfil", "perfil", JoinType.LEFT_OUTER_JOIN);
        criteria.setFetchMode("perfil", FetchMode.JOIN);
        
        if(nombres != null && !nombres.isEmpty()) {
            criteria.add(Restrictions.ilike("usuario.nombres", nombres, MatchMode.ANYWHERE));
        }
        if(apellidos != null && !apellidos.isEmpty()){
            criteria.add(Restrictions.ilike("usuario.apellidos", apellidos, MatchMode.ANYWHERE));
        }
        if(rut != null) {
            criteria.add(Restrictions.eq("usuario.rut", rut));
        }
        if(perfil != null) {
            criteria.add(Restrictions.eq("perfil", perfil));
        }
        if(email != null && !email.isEmpty()) {
            criteria.add(Restrictions.ilike("usuario.email", email, MatchMode.ANYWHERE));
        }
        if(fechaNacimientoInferior != null) {
            criteria.add(Restrictions.ge("usuario.fechaNacimiento", fechaNacimientoInferior));
        }
        if(fechaNacimientoSuperior != null) {
            criteria.add(Restrictions.le("usuario.fechaNacimiento", fechaNacimientoSuperior));
        }
        if(habilitado != null) {
            criteria.add(Restrictions.eq("usuario.habilitado", habilitado));
        }
        
        return criteria;
    }

}
